package it.aekidna.cleverplatypus.mediator
{
	import flash.utils.getQualifiedClassName;
	
	import mx.collections.ArrayCollection;
	import mx.logging.ILogger;
	import mx.logging.Log;

	public class CommandEvent
	{
		use namespace COMMAND_EVENT_INTERNAL;
		
		private static const DEFAULT_PRIORITY : uint = 5000;
		private static const HIGHEST_PRIORITY : uint = uint.MAX_VALUE;
		private static const LOWEST_PRIORITY : uint = uint.MIN_VALUE;
		
		private static const LOGGER : ILogger = 
			Log.getLogger( getQualifiedClassName( CommandEvent ).replace(/:+/g, "." ) );
		
		private static var pool : ArrayCollection = new ArrayCollection();
		
		private static var usedEvents : ArrayCollection = new ArrayCollection();
		
		COMMAND_EVENT_INTERNAL var parameters : Object;
		
		private var _type : String;
		private var _priority : uint = DEFAULT_PRIORITY;
		
		public static var bulkCreationSize : int = 10;
		
		public function CommandEvent( inEnforcer : SingletonEnforcer )
		{
		}
		
		public function get type() : String
		{
			return _type;
		}
		
		public static function createWithNamedParams( 
			inType : String, 
			inParams : Object = null, 
			inPriority : uint = DEFAULT_PRIORITY 
			) : CommandEvent
		{
			var event : CommandEvent = getInstance();
			event._type = inType;
			event._priority = inPriority;
			event.parameters = inParams;
			return event;
		} 
		
		public function dispatch() : CommandAsyncToken
		{
			if( !MediationRegistry.getInstance().willTrigger( type ) )
			{
				LOGGER.info( "The mediation event {0} is being dispatched but it has no listeners", type );
				return null;
			}
			return MediationRegistry.getInstance().mediate( this );
		}
		
		public function release() : void
		{
			_type = null;
			parameters = null;
			if( usedEvents.contains( this ) )
			{
				pool.addItem( 
					usedEvents.removeItemAt( 
						usedEvents.getItemIndex( this ) ) );
			}
			if( pool.length > bulkCreationSize * 2 )
			{
				for( var i : int = 0; i < bulkCreationSize; i++ )
				{
					pool.removeItemAt( 0 );
				}
			}
		}

		private static function getInstance() : CommandEvent
		{
			if( pool.length == 0 )
			{
				bulkCreate();
			}
			var event : CommandEvent = CommandEvent( pool.removeItemAt( 0 ) );
			usedEvents.addItem( event );
			return event;
		}
		
		private static function bulkCreate() : void
		{
			for( var i : int = 0; i < bulkCreationSize; i++ )
			{
				pool.addItem( new CommandEvent( new SingletonEnforcer() ) );
			}
		}
		
	}
}
class SingletonEnforcer {}